package com.maple.springbootinit.manager;


import com.maple.springbootinit.common.ErrorCode;
import com.maple.springbootinit.exception.BusinessException;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 专门提供 RedisLimiter 限流基础服务的（提供了通用的能力）
 */
@Service
public class RedisLimiterManager {

    @Resource
    private RedissonClient redissonClient;

    /**
     * 限流操作
     *
     * @param key 区分不同的限流器，比如不同的用户 id 应该分别统计
     */
    public void doRateLimit(String key) {
        /*
           创建一个名称为user_limiter的限流器，每秒最多访问 2 次
           RateType.OVERALL表示设置整体速率。在这种速率类型下，限流器会根据给定的速率限制整个操作过程的速度。
           2代表每秒的令牌发放数量。即限制每秒最多只允许通过2个请求或操作。
           1代表令牌发放间隔长度。在本例中，每秒发放2个令牌，间隔长度为1。
         */
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
        rateLimiter.trySetRate(RateType.OVERALL, 2, 1, RateIntervalUnit.SECONDS);
        // 每当一个操作来了后，请求一个令牌
        boolean canOp = rateLimiter.tryAcquire(1);
        if (!canOp) {
            throw new BusinessException(ErrorCode.TOO_MANY_REQUEST);
        }
    }
}
